#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
队列的实际应用示例
包含多种实际场景的队列应用
"""

from collections import deque
import time
import random

class PrintQueue:
    """打印队列管理"""
    
    def __init__(self):
        self.queue = deque()
        self.current_job = None
    
    def add_job(self, job_name, pages):
        """添加打印任务"""
        job = {
            'name': job_name,
            'pages': pages,
            'timestamp': time.time()
        }
        self.queue.append(job)
        print(f"打印任务已添加: {job_name} ({pages}页)")
    
    def process_next_job(self):
        """处理下一个打印任务"""
        if self.queue:
            job = self.queue.popleft()
            self.current_job = job
            print(f"正在打印: {job['name']} ({job['pages']}页)")
            # 模拟打印时间
            time.sleep(0.1)
            print(f"打印完成: {job['name']}")
            self.current_job = None
            return job
        else:
            print("没有待打印的任务")
            return None
    
    def get_queue_status(self):
        """获取队列状态"""
        return {
            'waiting_jobs': len(self.queue),
            'current_job': self.current_job['name'] if self.current_job else None
        }


class MessageQueue:
    """消息队列"""
    
    def __init__(self, max_size=100):
        self.queue = deque()
        self.max_size = max_size
        self.subscribers = []
    
    def subscribe(self, subscriber_name):
        """订阅消息"""
        self.subscribers.append(subscriber_name)
        print(f"{subscriber_name} 已订阅消息队列")
    
    def publish(self, message):
        """发布消息"""
        if len(self.queue) >= self.max_size:
            print("消息队列已满，丢弃最旧的消息")
            self.queue.popleft()
        
        msg = {
            'content': message,
            'timestamp': time.time(),
            'id': random.randint(1000, 9999)
        }
        self.queue.append(msg)
        print(f"消息已发布: {message}")
    
    def consume(self, subscriber_name):
        """消费消息"""
        if subscriber_name not in self.subscribers:
            print(f"{subscriber_name} 未订阅消息队列")
            return None
        
        if self.queue:
            message = self.queue.popleft()
            print(f"{subscriber_name} 收到消息: {message['content']}")
            return message
        else:
            print(f"{subscriber_name}: 没有新消息")
            return None


class WebServer:
    """Web服务器请求队列"""
    
    def __init__(self, max_concurrent=5):
        self.request_queue = deque()
        self.max_concurrent = max_concurrent
        self.active_requests = 0
    
    def handle_request(self, request):
        """处理请求"""
        if self.active_requests >= self.max_concurrent:
            # 服务器繁忙，加入队列等待
            self.request_queue.append(request)
            print(f"服务器繁忙，请求 {request['id']} 已加入等待队列")
        else:
            # 直接处理请求
            self._process_request(request)
    
    def _process_request(self, request):
        """处理单个请求"""
        self.active_requests += 1
        print(f"正在处理请求 {request['id']}: {request['url']}")
        
        # 模拟处理时间
        time.sleep(random.uniform(0.1, 0.5))
        
        print(f"请求 {request['id']} 处理完成")
        self.active_requests -= 1
        
        # 处理队列中的下一个请求
        if self.request_queue:
            next_request = self.request_queue.popleft()
            self._process_request(next_request)


class BreadthFirstSearch:
    """广度优先搜索示例"""
    
    def __init__(self):
        self.graph = {
            'A': ['B', 'C'],
            'B': ['A', 'D', 'E'],
            'C': ['A', 'F'],
            'D': ['B'],
            'E': ['B', 'F'],
            'F': ['C', 'E']
        }
    
    def bfs(self, start, target=None):
        """广度优先搜索"""
        visited = set()
        queue = deque([(start, [start])])  # (节点, 路径)
        visited.add(start)
        
        while queue:
            vertex, path = queue.popleft()
            print(f"访问节点: {vertex}, 路径: {' -> '.join(path)}")
            
            # 如果找到目标节点
            if target and vertex == target:
                print(f"找到目标节点 {target}，路径: {' -> '.join(path)}")
                return path
            
            # 遍历邻居节点
            for neighbor in self.graph.get(vertex, []):
                if neighbor not in visited:
                    visited.add(neighbor)
                    queue.append((neighbor, path + [neighbor]))
        
        return None
    
    def shortest_path(self, start, end):
        """寻找最短路径"""
        return self.bfs(start, end)


class TaskScheduler:
    """任务调度器"""
    
    def __init__(self):
        self.task_queue = deque()
        self.completed_tasks = []
        self.current_task = None
    
    def add_task(self, task_name, priority=1, duration=1):
        """添加任务"""
        task = {
            'name': task_name,
            'priority': priority,
            'duration': duration,
            'created_at': time.time()
        }
        
        # 按优先级插入任务
        inserted = False
        for i, existing_task in enumerate(self.task_queue):
            if task['priority'] > existing_task['priority']:
                self.task_queue.insert(i, task)
                inserted = True
                break
        
        if not inserted:
            self.task_queue.append(task)
        
        print(f"任务已添加: {task_name} (优先级: {priority})")
    
    def execute_next_task(self):
        """执行下一个任务"""
        if self.task_queue:
            task = self.task_queue.popleft()
            self.current_task = task
            print(f"开始执行任务: {task['name']}")
            
            # 模拟任务执行
            time.sleep(task['duration'] * 0.1)
            
            print(f"任务完成: {task['name']}")
            self.completed_tasks.append(task)
            self.current_task = None
            return task
        else:
            print("没有待执行的任务")
            return None
    
    def get_status(self):
        """获取调度器状态"""
        return {
            'pending_tasks': len(self.task_queue),
            'completed_tasks': len(self.completed_tasks),
            'current_task': self.current_task['name'] if self.current_task else None
        }


def demo_print_queue():
    """演示打印队列"""
    print("=" * 60)
    print("打印队列演示")
    print("=" * 60)
    
    printer = PrintQueue()
    
    # 添加打印任务
    printer.add_job("报告.pdf", 10)
    printer.add_job("图片.jpg", 1)
    printer.add_job("文档.docx", 5)
    printer.add_job("表格.xlsx", 3)
    
    print(f"\n队列状态: {printer.get_queue_status()}")
    
    # 处理打印任务
    while printer.queue:
        printer.process_next_job()
        print(f"队列状态: {printer.get_queue_status()}")


def demo_message_queue():
    """演示消息队列"""
    print("\n" + "=" * 60)
    print("消息队列演示")
    print("=" * 60)
    
    mq = MessageQueue(max_size=5)
    
    # 订阅者
    mq.subscribe("用户A")
    mq.subscribe("用户B")
    mq.subscribe("用户C")
    
    # 发布消息
    messages = ["系统维护通知", "新功能发布", "安全更新", "性能优化"]
    for msg in messages:
        mq.publish(msg)
    
    print(f"\n队列中有 {len(mq.queue)} 条消息")
    
    # 消费消息
    subscribers = ["用户A", "用户B", "用户C"]
    while mq.queue:
        for subscriber in subscribers:
            mq.consume(subscriber)
            if not mq.queue:
                break


def demo_web_server():
    """演示Web服务器"""
    print("\n" + "=" * 60)
    print("Web服务器请求队列演示")
    print("=" * 60)
    
    server = WebServer(max_concurrent=2)
    
    # 模拟请求
    requests = [
        {'id': 1, 'url': '/home'},
        {'id': 2, 'url': '/about'},
        {'id': 3, 'url': '/contact'},
        {'id': 4, 'url': '/products'},
        {'id': 5, 'url': '/services'},
        {'id': 6, 'url': '/blog'}
    ]
    
    for request in requests:
        server.handle_request(request)


def demo_bfs():
    """演示广度优先搜索"""
    print("\n" + "=" * 60)
    print("广度优先搜索演示")
    print("=" * 60)
    
    bfs = BreadthFirstSearch()
    
    print("从节点A开始的BFS遍历:")
    bfs.bfs('A')
    
    print(f"\n从A到F的最短路径:")
    path = bfs.shortest_path('A', 'F')
    if path:
        print(f"最短路径: {' -> '.join(path)}")


def demo_task_scheduler():
    """演示任务调度器"""
    print("\n" + "=" * 60)
    print("任务调度器演示")
    print("=" * 60)
    
    scheduler = TaskScheduler()
    
    # 添加不同优先级的任务
    tasks = [
        ("备份数据库", 3, 2),
        ("发送邮件", 1, 1),
        ("清理缓存", 2, 1),
        ("生成报告", 3, 3),
        ("更新日志", 1, 1)
    ]
    
    for task_name, priority, duration in tasks:
        scheduler.add_task(task_name, priority, duration)
    
    print(f"\n调度器状态: {scheduler.get_status()}")
    
    # 执行任务
    while scheduler.task_queue:
        scheduler.execute_next_task()
        print(f"调度器状态: {scheduler.get_status()}")


def main():
    """主函数"""
    print("队列实际应用示例演示程序")
    print("=" * 60)
    
    # 运行所有演示
    demo_print_queue()
    demo_message_queue()
    demo_web_server()
    demo_bfs()
    demo_task_scheduler()
    
    print("\n" + "=" * 60)
    print("所有演示完成！")
    print("=" * 60)


if __name__ == "__main__":
    main()
